home *** CD-ROM | disk | FTP | other *** search
- #include <Inventor/SoPath.h>
- #include <Inventor/actions/SoSearchAction.h>
- #include <Inventor/nodes/SoSeparator.h>
- #include <Inventor/nodes/SoCoordinate3.h>
- #include <Inventor/nodes/SoNormal.h>
- #include <Inventor/SoDetail.h>
-
- //
- // Several methods of SoDetail subclasses call an internal routine
- // that creates a SoSearchAction but fails to delete it. This causes
- // a large memory leak (the searchAction, all of the paths it finds,
- // and all of the nodes on those paths will never be deleted) and will
- // cause the application to slow down because of the extra paths.
- //
- // To fix this, compile this file into a .o and then link
- // the .o before -lInventor_s. The linker will give warnings like:
- // Warning: getCoordinate3Node__19SoVertexShapeDetailCFv: multiply defined
- // previous (used) definition from 'detail.o';
- // new (ignored) definition from '/usr/lib/libInventor_s.a'
- // This is normal and expected.
- //
-
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Return the coordinate node that affects this shape.
- //
- // Use: protected
-
- SoCoordinate3 *
- SoVertexShapeDetail::getCoordinate3Node() const
- //
- ////////////////////////////////////////////////////////////////////////
- {
- return
- (SoCoordinate3 *) getLastPropertyNode(SoCoordinate3::getClassTypeId());
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Return the normal node that affects this shape, NULL if
- // there isn't one.
- //
- // Use: protected
-
- SoNormal *
- SoVertexShapeDetail::getNormalNode() const
- //
- ////////////////////////////////////////////////////////////////////////
- {
- return
- (SoNormal *) getLastPropertyNode(SoNormal::getClassTypeId());
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Returns the node of the given type that affects the shape that
- // this detail's path leads to. The passed property node should
- // be one that does not accumulate such as, oh, gosh,
- // maybe a Normal or a Coordinate3 node, because we look
- // for the last (and hence current) one.
- //
- //
- // Use: private
-
- SoNode *
- SoVertexShapeDetail::getLastPropertyNode(SoType typeId) const
- //
- ////////////////////////////////////////////////////////////////////////
- {
- #ifdef DEBUG
- if (path == NULL) {
- fprintf( stderr, "SoVertexShapeDetail::getLastPropertyNode - " );
- fprintf( stderr, "path to shape is NULL\n" );
- return NULL;
- }
- #endif
-
- SoNode *result;
-
- if (path->getTail()->isOfType(typeId)) {
- // path already leads to a node of given type, so just return it
- result = path->getTail();
- }
- else {
- // Apply a search action to the path, and look
- // for the _last_ node of the requested type
-
- SoSearchAction sa;
- sa.setType(typeId);
- sa.setFindAll(TRUE);
- sa.apply(path);
-
- SoPathList paths = sa.getPaths();
-
- if (paths.length() == 0) {
- // nothing found
- result = NULL;
- }
- else {
- // return the last one found
- result = paths[paths.length() - 1]->getTail();
- }
- }
-
- return result;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Return the point detail information.
- //
- // Use: public
-
- void
- SoPointDetail::getPoint(
- long &_coordIndex, SoCoordinate3 *&coordNode,
- long &_normalIndex, SoNormal *&normalNode) const
-
- //
- ////////////////////////////////////////////////////////////////////////
- {
- _coordIndex = coordIndex;
- _normalIndex = normalIndex;
-
- coordNode = getCoordinate3Node();
- if (normalIndex == SO_DETAIL_NO_NORMAL_NODE)
- normalNode = NULL;
- else
- normalNode = getNormalNode();
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Return the line detail information.
- //
- // Use: public
-
- void
- SoLineDetail::getLine(
- long &_coordIndex0, long &_coordIndex1,
- SoCoordinate3 *&coordNode,
- long &_normalIndex0, long &_normalIndex1,
- SoNormal *&normalNode) const
- //
- ////////////////////////////////////////////////////////////////////////
- {
- _coordIndex0 = coordIndex0;
- _coordIndex1 = coordIndex1;
-
- _normalIndex0 = normalIndex0;
- _normalIndex1 = normalIndex1;
-
- coordNode = getCoordinate3Node();
-
- if (normalIndex0 == SO_DETAIL_NO_NORMAL_NODE)
- normalNode = NULL;
- else
- normalNode = getNormalNode();
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // return the detail about the closest point
- //
- // Use: virtual public
-
- const SoPointDetail &
- SoLineDetail::getClosestPoint()
- {
- long closeCoordIndex;
- long closeNormalIndex;
-
- SoCoordinate3 *coordNode = getCoordinate3Node();
-
- float dist0 = (point - coordNode->point[(int) coordIndex0]).length();
- float dist1 = (point - coordNode->point[(int) coordIndex1]).length();
-
- if (dist0 < dist1) {
- closeCoordIndex = coordIndex0;
- closeNormalIndex = normalIndex0;
- }
- else {
- closeCoordIndex = coordIndex1;
- closeNormalIndex = normalIndex1;
- }
-
- pointDetail.setPointCoordinate(closeCoordIndex);
- pointDetail.setPoint(coordNode->point[(int) closeCoordIndex]);
-
- if (closeNormalIndex == SO_DETAIL_NO_NORMAL_NODE) {
- pointDetail.setNormal(normal);
- }
- else {
- pointDetail.setPointNormal(closeNormalIndex);
-
- SoNormal *normalNode = getNormalNode();
- if (normalNode)
- pointDetail.setNormal(normalNode->vector[(int) closeNormalIndex]);
- else
- pointDetail.setNormal(normal);
- }
-
- pointDetail.setPath(path);
- pointDetail.setMatrix(objToWorld);
- pointDetail.setUnits(unitsType);
-
- return pointDetail;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // Return the line detail information.
- //
- // Use: public
-
- void
- SoFaceDetail::getFace(
- long &_numCoords, long *&_coordIndexList,
- SoCoordinate3 *&coordNode,
- long &_numNormals, long *&_normalIndexList,
- SoNormal *&normalNode) const
- //
- ////////////////////////////////////////////////////////////////////////
- {
- _numCoords = numCoords;
- _coordIndexList = coordIndexList;
- _numNormals = numNormals;
- _normalIndexList = normalIndexList;
-
- coordNode = getCoordinate3Node();
-
- if (numNormals == SO_DETAIL_NO_NORMAL_NODE)
- normalNode = NULL;
- else
- normalNode = getNormalNode();
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // return the detail about the closest point
- //
- // Use: virtual public
-
- const SoPointDetail &
- SoFaceDetail::getClosestPoint()
- {
- SoCoordinate3 *coordNode = getCoordinate3Node();
-
- float minDist = (point -coordNode->point[(int)coordIndexList[0]]).length();
- long closeCoordIndex = 0;
- long closeNormalIndex = 0;
-
- for (int i = 1; i < numCoords; i++) {
- float dist =
- (point - coordNode->point[(int)coordIndexList[i]]).length();
-
- if (dist < minDist) {
- minDist = dist;
- closeCoordIndex = i;
-
- if (numNormals != 1)
- closeNormalIndex = i;
- }
- }
-
- pointDetail.setPointCoordinate(coordIndexList[closeCoordIndex]);
- pointDetail.setPoint(coordNode->point[
- (int)coordIndexList[closeCoordIndex]]);
-
- if (numNormals == SO_DETAIL_NO_NORMAL_NODE) {
- pointDetail.setNormal(normal);
- }
- else {
- pointDetail.setPointNormal(normalIndexList[closeNormalIndex]);
-
- SoNormal *normalNode = getNormalNode();
- if (normalNode)
- pointDetail.setNormal(
- normalNode->vector[(int)normalIndexList[closeNormalIndex]]);
- else
- pointDetail.setNormal(normal);
-
- }
-
- pointDetail.setPath(path);
- pointDetail.setMatrix(objToWorld);
- pointDetail.setUnits(unitsType);
-
- return pointDetail;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Description:
- // return the detail about the closest line
- //
- // Use: virtual public
-
- const SoLineDetail &
- SoFaceDetail::getClosestLine()
- {
-
- SoCoordinate3 *coordNode = getCoordinate3Node();
-
- // Start with the edge that goes from the last to the first point
- SbLine edge(
- coordNode->point[(int)coordIndexList[numCoords - 1]],
- coordNode->point[(int)coordIndexList[0]]);
-
- SbVec3f closePoint = edge.getClosestPoint(point);
- float minDist = (point - closePoint).length();
- long closeCoordIndex = numCoords - 1;
-
- for (int i = 0; i < numCoords - 1; i++) {
- edge.setValue(
- coordNode->point[(int)coordIndexList[i]],
- coordNode->point[(int)coordIndexList[i+1]]);
-
- SbVec3f edgePoint = edge.getClosestPoint(point);
- float dist = (point - edgePoint).length();
-
- if (dist < minDist) {
- minDist = dist;
- closePoint = edgePoint;
- closeCoordIndex = i;
- }
- }
-
- // Fill the the coordinate indices for the detail
- long c0, c1, n0, n1; // indices of the coord and normal
-
- if (closeCoordIndex == numCoords - 1) {
- c0 = coordIndexList[numCoords - 1];
- c1 = coordIndexList[0];
- }
- else {
- c0 = coordIndexList[closeCoordIndex];
- c1 = coordIndexList[closeCoordIndex + 1];
- }
-
- // Indices of the coordinates
- lineDetail.setLineCoordinates(c0, c1);
-
- // Set the detail point to be the close point on the edge
- lineDetail.setPoint(closePoint);
-
- // Fill in the normal indices for the detail
- if (numNormals == SO_DETAIL_NO_NORMAL_NODE) {
- n0 = n1 = SO_DETAIL_NO_NORMAL_NODE;
- }
- else {
- if (numNormals == 1) {
- // Overall
- n0 = n1 = 0;
- }
- else {
- // Per vertex
- if (closeCoordIndex == numCoords - 1) {
- n0 = normalIndexList[closeCoordIndex - 1];
- n1 = normalIndexList[0];
- }
- else {
- n0 = normalIndexList[closeCoordIndex];
- n1 = normalIndexList[closeCoordIndex + 1];
- }
-
- }
- }
-
- lineDetail.setLineNormals(n0, n1);
-
- // Fill in the normal for the detail point.
- SbVec3f edgeNormal; // the normal at the closePoint on the edge
-
- if (numNormals == SO_DETAIL_NO_NORMAL_NODE) {
- // Default normal
- edgeNormal = normal;
- }
- else {
- SoNormal *normalNode = getNormalNode();
-
- if (! normalNode) {
- edgeNormal = normal;
- }
- else {
- if (numNormals == 1) {
- // Overall
- edgeNormal = normalNode->vector[(int) normalIndexList[0]];
- }
- else {
- // Per vertex
- // Interpolate the normal along the edge
-
- SbVec3f norm0, norm1, coord0, coord1;
-
- coord0 = coordNode->point[(int)c0];
- coord1 = coordNode->point[(int)c1];
-
- norm0 = normalNode->vector[(int)n0];
- norm1 = normalNode->vector[(int)n1];
-
- float dist0 = (closePoint - coord0).length();
- float dist = (coord1 - coord0).length();
-
- edgeNormal = norm0 + (dist0/dist) * (norm1 - norm0);
- }
- }
- }
-
- lineDetail.setNormal(edgeNormal);
-
- // This stuff doesn't change.
- lineDetail.setPath(path);
- lineDetail.setMatrix(objToWorld);
- lineDetail.setUnits(unitsType);
-
- return lineDetail;
- }
-